home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / SDKs / Word Services SDK 1.0.6 / Writeswell Jr 1.2.1 Sources ƒ / Writeswell Jr. Source / MyFiles.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-14  |  12.2 KB  |  643 lines  |  [TEXT/KAHL]

  1. /* MyFiles.c
  2.  * Handle file calls in IAC speller testbed app
  3.  * ©1992 Working Software, Inc.
  4.  * This source code is copyrighted.  Permission is granted to use the Word Services
  5.  * portion of the Writeswell Jr. source code in your own programs, but you 
  6.  * may not distribute the Writeswell Jr. word-processor code as a 
  7.  * commercial product.  If you modify the code, please do not call it 
  8.  * Writeswell Jr. (or Writeswell.)  This will ensure that people understand the 
  9.  * program and don’t have to deal with a number of different versions with 
  10.  * who-knows-what going on in the code.
  11.  * 
  12.  * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
  13.  * 6 Sep 91 Mike Crawford
  14.  */
  15.  
  16. #include <Files.h>
  17. #include "MyFiles.h"
  18. #include "AppleEvents.h"
  19. #include "TestBed.h"
  20. #include "TBConstants.h"
  21. #include "TBGlobals.h"
  22. #include "Scroll.h"
  23. #include "Gripe.h"
  24. #include "TTPictures.h"
  25. #include "FontMenu.h"
  26. #include "Prefs.h"
  27.  
  28. #define kZoomIconAllowance    68        /* Width of desktop to show when window zoomed */
  29.  
  30. OSErr SaveStyleResource( void );
  31. short CountTTPictures( void );
  32. short AskSave( void );
  33.  
  34. void DoOpenDialog( void )
  35. {
  36.     SFTypeList    typeList;
  37.     SFReply        reply;
  38.     Point        where;
  39.     
  40.     typeList[ 0 ] = 'TEXT';
  41.     typeList[ 1 ] = 'ttro';
  42.  
  43.     /* STUB Center the dialog */
  44.     
  45.     where.h = 50;
  46.     where.v = 50;
  47.  
  48.     SFGetFile( where,
  49.                     "\p",
  50.                     (FileFilterUPP)NULL,
  51.                     2,
  52.                     typeList,
  53.                     (DlgHookUPP)NULL,
  54.                     &reply );
  55.     
  56.     if ( !reply.good )
  57.         return;
  58.     
  59.     MyOpenSfFile( &reply );
  60.  
  61.     return;
  62. }
  63.  
  64. void DoSave( void )
  65. {
  66.     Boolean    saved;
  67.  
  68.     if ( gDocExists )
  69.         SaveFile();
  70.     else
  71.         DoSaveDialog( &saved );
  72.     return;
  73. }
  74.  
  75. OSErr DoSaveAs( void )
  76. {
  77.     OSErr    err;
  78.     short    oldRefNum;
  79.     short    oldResRefNum;
  80.     Boolean    docExisted;
  81.     Boolean    saved;
  82.     
  83.     docExisted = gDocExists;
  84.     
  85.     if ( docExisted ){
  86.         oldRefNum = gRefNum;
  87.         oldResRefNum = gResRefNum;
  88.     }
  89.     
  90.     err = DoSaveDialog( &saved );
  91.     
  92.     if ( docExisted && saved ){
  93.         err = FSClose( oldRefNum );
  94.         if ( err ){
  95.             Gripe( "\pCould not close original file" );
  96.             return err;
  97.         }
  98.         
  99.         if ( oldResRefNum != -1 ){
  100.             err = CopyPictures( oldResRefNum, gResRefNum );
  101.  
  102.             if ( err ){
  103.                 Gripe( "\pCould not copy pictures to new file" );
  104.                 return err;
  105.             }
  106.  
  107.             CloseResFile( oldResRefNum );
  108.             err = ResError();
  109.             if ( err ){
  110.                 Gripe( "\pCould not close original resource file" );
  111.                 return err;
  112.             }
  113.         }
  114.     }
  115.  
  116.     return noErr;
  117. }
  118.  
  119. OSErr DoSaveDialog( Boolean *savedPtr )
  120. {
  121.     SFReply        reply;
  122.     OSErr        err;
  123.     Point        where;
  124.     
  125.     *savedPtr = false;
  126.  
  127.     /* STUB Center the dialog on the screen */
  128.     
  129.     where.h = 100;
  130.     where.v = 50;
  131.  
  132.     /* STUB use the window name as the default name */
  133.     
  134.     SFPutFile( where,
  135.                 "\pSave document as:",
  136.                 "\pUntitled",
  137.                 (DlgHookUPP)NULL,
  138.                 &reply );
  139.     
  140.     if ( !reply.good )
  141.         return noErr;
  142.     
  143.     /* Try deleting the old file.  It may not exist.
  144.      * STUB Do a GetFileInfo to see if the file already exists
  145.      */
  146.     
  147.     err = FSDelete( reply.fName, reply.vRefNum );
  148.     if ( err && err != fnfErr ){
  149.         Gripe( "\pCould not delete existing file" );
  150.         return err;
  151.     }
  152.     
  153.     err = Create( reply.fName,
  154.                     reply.vRefNum,
  155.                     'MiKe',
  156.                     'TEXT' );
  157.     if ( err ){
  158.         Gripe( "\pCould not create new file" );
  159.         return err;
  160.     }
  161.     
  162.     if ( err = FSOpen( reply.fName, reply.vRefNum, &gRefNum ) ){
  163.         Gripe( "\pFSOpen failed" );
  164.         return err;
  165.     }
  166.     
  167.     err = SetVol( (StringPtr)NULL, reply.vRefNum );
  168.     if ( err ){
  169.         Gripe( "\pCould not set volume" );
  170.         return err;
  171.     }
  172.  
  173.     CreateResFile( reply.fName );
  174.     if ( err = ResError() ){
  175.         Gripe( "\pCould not create resource fork of document" );
  176.         return err;
  177.     }
  178.  
  179.     gResRefNum = OpenResFile( reply.fName );
  180.     if ( gResRefNum == -1 ){
  181.         err = ResError();
  182.         Gripe( "\pOpenResFile failed" );
  183.         return err;
  184.     }
  185.  
  186.     gDocExists = true;
  187.     
  188.     err = SaveFile();
  189.  
  190.     if ( !err ){
  191.         SetWTitle( gDocWindow, reply.fName );
  192.         *savedPtr = true;
  193.     }
  194.  
  195.     return err;
  196. }
  197.  
  198. OSErr CopyPictures( short oldFile, short newFile )
  199. {
  200.     short    numPix;
  201.     short    curFile;
  202.     short    i;
  203.     OSErr    err;
  204.     short    resNum;
  205.     
  206.     curFile = CurResFile();
  207.     UseResFile( oldFile );
  208.     
  209.     numPix = CountTTPictures();
  210.     
  211.     for ( i = 0; i < numPix; i++ ){
  212.     
  213.         resNum = 1000 + i;
  214.     
  215.         err = CopyResource( resNum, resNum, 'PICT', oldFile, newFile );
  216.         
  217.         if ( err ){
  218.             UseResFile( curFile );
  219.             return err;
  220.         }
  221.     }
  222.     
  223.     UseResFile( curFile );
  224.     
  225.     
  226.     return noErr;
  227. }
  228.  
  229. OSErr SaveFile( void )
  230. {
  231.     OSErr        err;
  232.     TEHandle    textH;
  233.     CharsHandle    textBufHdl;
  234.     long        numChars;
  235.  
  236.     /* STUB should do a "safe save" here.  This is not a safe save - if there is 
  237.      * a failure in here, the file is hosed.
  238.      */
  239.  
  240.     err = SetFPos( gRefNum, fsFromStart, 0L );
  241.     if ( err ){
  242.         Gripe( "\pCould not set file position" );
  243.         return err;
  244.     }
  245.  
  246.     err = SetEOF( gRefNum, 0L );
  247.     if ( err ){
  248.         Gripe( "\pCould not set end of file" );
  249.         return err;
  250.     }
  251.  
  252.     textH = (TEHandle)GetWRefCon( gDocWindow );
  253.     
  254.     textBufHdl = TEGetText( textH );
  255.     
  256.     numChars = GetHandleSize( textBufHdl );
  257.     
  258.     HLock( textBufHdl );
  259.     err = FSWrite( gRefNum, &numChars, *textBufHdl );
  260.     HUnlock( textBufHdl );
  261.     
  262.     if ( err ){
  263.         Gripe( "\pFSWrite failed" );
  264.         return err;
  265.     }
  266.     
  267.     err = SaveStyleResource();
  268.     
  269.     if ( !err )
  270.         gDocDirty = false;
  271.  
  272.     return err;
  273. }
  274.  
  275. OSErr SaveStyleResource( void )
  276. {
  277.     short            curFile;
  278.     StScrpHandle    styleHdl;
  279.     TEHandle        textH;
  280.     Handle            oldStyle;
  281.     short            oldStart;
  282.     short            oldEnd;
  283.     
  284.     curFile = CurResFile();
  285.     
  286.     UseResFile( gResRefNum );
  287.     
  288.     textH = (TEHandle)GetWRefCon( gDocWindow );
  289.     
  290.     oldStart = (*textH)->selStart;
  291.     oldEnd = (*textH)->selEnd;
  292.  
  293.     (*textH)->selStart = 0;
  294.     (*textH)->selEnd = 32767;
  295.  
  296.     styleHdl = GetStylScrap( textH );
  297.     
  298.     (*textH)->selStart = oldStart;
  299.     (*textH)->selEnd = oldEnd;
  300.  
  301.     if ( !styleHdl ){
  302.         UseResFile( curFile );
  303.         return memFullErr;
  304.     }
  305.     
  306.     oldStyle = Get1Resource( 'styl', rStyleID );
  307.     
  308.     if ( oldStyle ){
  309.         RmveResource( oldStyle );    
  310.     }
  311.  
  312.     AddResource( (Handle) styleHdl, 'styl', rStyleID, "\pText Styles" );
  313.     ChangedResource( (Handle) styleHdl );
  314.     WriteResource( (Handle) styleHdl );
  315.  
  316.     UpdateResFile( gResRefNum );
  317.  
  318.     UseResFile( curFile );
  319.  
  320.     return noErr;
  321. }
  322.  
  323. OSErr MyOpenSfFile( SFReply *replyPtr )
  324. {
  325.     OSErr            err;
  326.     char            *textBuf;
  327.     long            bytesRead;
  328.     TEHandle        textH;
  329.     StScrpHandle    styleHdl;
  330.     ParamBlockRec    fPB;
  331.     long            fileSize;
  332.     
  333.     if ( err = FSOpen( replyPtr->fName, replyPtr->vRefNum, &gRefNum ) ){
  334.         Gripe( "\pFSOpen failed" );
  335.         return err;
  336.     }
  337.     
  338.     fPB.fileParam.ioCompletion = (IOCompletionUPP)NULL;
  339.     fPB.fileParam.ioNamePtr = (StringPtr)NULL;
  340.     fPB.fileParam.ioVRefNum = replyPtr->vRefNum;
  341.     
  342.     err = PBSetVol( &fPB, false );
  343.     if ( err ){
  344.         Gripe( "\pPBSetVol failed in MyOpenSfFile" );
  345.         return err;
  346.     }
  347.  
  348.     gResRefNum = OpenResFile( replyPtr->fName );
  349.     
  350.     /* The existing file may have had no resource fork.  It's not clear to me
  351.      * what the right thing to do is.  I am inclined to not create one - if the
  352.      * user wants to save styles, she could do a "Save As" to create a new file
  353.      * with the style resource.
  354.      */
  355.  
  356.     styleHdl = (StScrpHandle)NULL;            /* In case there's no resource fork */
  357.  
  358.     if ( gResRefNum != -1 ){
  359.  
  360.         /* Load the style resource */
  361.         
  362.         styleHdl = (StScrpHandle)Get1Resource( 'styl', rStyleID );
  363.         
  364.         /* styleHdl might be nil - we check for this later */
  365.         
  366.         /* 2.0 Count the number of TeachText-style pictures */
  367.         gNumPictures = CountTTPictures();
  368.     }else{
  369.         gNumPictures = 0;
  370.     }
  371.     
  372.     if ( MakeNewWindow() ){
  373.         Gripe( "\pMakeNewWindow failed" );
  374.         return err;
  375.     }
  376.     
  377.     gDocExists = true;
  378.  
  379.     SetWTitle( gDocWindow, replyPtr->fName );
  380.  
  381.     textH = (TEHandle)GetWRefCon( gDocWindow );
  382.  
  383.     /* Styled TextEdit requires that we insert the text and the style at the same time.
  384.      * I originally had a loop that did a read with a small buffer, but in order to
  385.      * set both the text and the style, I need to read all of the text in a single
  386.      * chunk, and set it in a single chunk.
  387.      */
  388.     
  389.     err = GetEOF( gRefNum, &fileSize );
  390.     if ( err ){
  391.         Gripe( "\pCould not get file size" );
  392.         return err;
  393.     }
  394.  
  395.     textBuf = NewPtr( fileSize );
  396.     if ( !textBuf ){
  397.         Gripe( "\pOut of memory" );
  398.         return memFullErr;
  399.     }
  400.  
  401.     bytesRead = fileSize;
  402.  
  403.     err = FSRead( gRefNum, &bytesRead, textBuf );
  404.     
  405.     if ( err ){
  406.         Gripe( "\pCould not read the file" );
  407.         DisposPtr( textBuf );
  408.         return err;
  409.     }
  410.     
  411.     /* styleHdl might be nil.  This is OK */
  412.     TEStylInsert( textBuf, bytesRead, styleHdl, textH );
  413.     
  414.     if ( styleHdl != (StScrpHandle)NULL )
  415.         ReleaseResource( (Handle) styleHdl );
  416.  
  417.     DisposPtr( textBuf );            /* 1.1.1 MDC fix a leak - didn't dispose this before */
  418.  
  419.     TESetSelect( 0L, 0L, textH );
  420.     
  421.     ShowPictures( gDocWindow, gNumPictures, gResRefNum );
  422.  
  423.     SetVertScroll( gDocWindow, gVertScroll );
  424.     
  425.     switch ( replyPtr->fType ){
  426.     
  427.         case 'TEXT':
  428.             gReadOnly = false;
  429.             break;
  430.         case 'ttro':
  431.             gReadOnly = true;
  432.             break;
  433.         default:
  434.             gReadOnly = false;
  435.             break;
  436.     }
  437.  
  438.     // 1.2.1 MDC We would leave a watch cursor up on the screen when opening a file
  439.     // from the DeskTop
  440.     
  441.     InitCursor();
  442.  
  443.     return noErr;
  444. }
  445.  
  446. OSErr MyOpenSpecFile( FSSpec *specPtr )
  447. {
  448.     WDPBRec            wPB;
  449.     SFReply            reply;
  450.     HParamBlockRec    hPB;
  451.     OSErr            err;
  452.     
  453.     wPB.ioCompletion = (IOCompletionUPP)NULL;
  454.     wPB.ioVRefNum = specPtr->vRefNum;
  455.     wPB.ioWDDirID = specPtr->parID;
  456.     wPB.ioWDProcID = 'ERIK';            /* This is traditional; no real point to it */
  457.     wPB.ioNamePtr = (StringPtr)NULL;
  458.  
  459.     err = PBOpenWD( &wPB, false );
  460.     if ( err ){
  461.         Gripe( "\pPBOpenWD failed in MyOpenSpecFile" );
  462.         return err;
  463.     }
  464.     
  465.     BlockMove( specPtr->name, reply.fName, (specPtr->name)[0] + 1 );
  466.     
  467.     reply.vRefNum = wPB.ioVRefNum;
  468.     
  469.     reply.good = true;
  470.     
  471.     reply.copy = false;
  472.  
  473.     /* 2.0 Check the file type so we can tell if it is a read-only document
  474.      * and perhaps check for EPS and PICT in the future
  475.      */
  476.         
  477.     hPB.fileParam.ioCompletion = (IOCompletionUPP)NULL;
  478.     hPB.fileParam.ioNamePtr = specPtr->name;
  479.     hPB.fileParam.ioVRefNum = specPtr->vRefNum;
  480.     hPB.fileParam.ioDirID = specPtr->parID;
  481.     hPB.fileParam.ioFDirIndex = 0;
  482.  
  483.     err = PBHGetFInfo( &hPB, false );
  484.     if ( err ){
  485.         Gripe( "\pPBHGetFInfo failed in MyOpenSpecFile" );
  486.         return err;
  487.     }
  488.  
  489.     reply.fType = hPB.fileParam.ioFlFndrInfo.fdType;
  490.  
  491.     reply.version = 0;
  492.     
  493.     err = MyOpenSfFile( &reply );
  494.     
  495.     return err;
  496. }
  497.  
  498. OSErr MakeNewWindow( void )
  499. {
  500.     OSErr        err = noErr;
  501.     Rect        txRect;
  502.     TEHandle    textH;
  503.     Rect        *zoomArray;
  504.     TEClickLoopUPP    trackerUPP;
  505.  
  506.     gDocWindow = GetNewWindow( kDocWindowID, (Ptr)NULL, (WindowPtr) -1 );
  507.     if ( !gDocWindow ){
  508.         Gripe( "\pGetNewWindow failed" );
  509.         return err;
  510.     }
  511.     
  512.     SetPort( gDocWindow );
  513.     
  514.     gDocDirty = false;
  515.     gDocExists = false;
  516.     
  517.     GetTERect( &qd.thePort->portRect, &txRect );
  518.     
  519.     textH = TEStylNew( &txRect, &txRect );
  520.     
  521.     if ( !textH ){
  522.         Gripe( "\pTENew failed" );
  523.         return memFullErr;
  524.     }
  525.     
  526.     SetWRefCon( gDocWindow, (long)textH );
  527.     
  528.     gVertScroll = GetNewControl( kVertScrollBarID, gDocWindow );
  529.     if ( !gVertScroll )
  530.         return memFullErr;
  531.  
  532.     trackerUPP = NewTEClickLoopProc( TrackContentClick );
  533.     if ( !trackerUPP )
  534.         return memFullErr;
  535.  
  536.     ( *textH )->clickLoop = (TEClickLoopUPP)trackerUPP;
  537.  
  538.     SizeVertScroll();
  539.  
  540.     SetVertScroll( gDocWindow, gVertScroll );
  541.     
  542.     if ( ((WindowPeek)gDocWindow)->dataHandle != (Handle)NULL ){
  543.         /* Set the zoom state to reveal the disk & trash icons.
  544.          * STUB Make this some kind of preference - inappropriate for Unifinder
  545.          */
  546.     
  547.         zoomArray = (Rect*)*((WindowPeek)gDocWindow)->dataHandle;        /* Warning: Deref handle */
  548.         
  549.         zoomArray[ 1 ].right -= kZoomIconAllowance;
  550.     }
  551.  
  552.     return noErr;
  553.     
  554. }
  555.  
  556. short CountTTPictures( void )
  557. {
  558.     short    numPix;
  559.     Handle    picHdl;
  560.     
  561.     /* This does not actually load the pictures into memory */
  562.     
  563.     SetResLoad( false );
  564.     
  565.     numPix = 0;
  566.     
  567.     do {
  568.         picHdl = GetResource( 'PICT', 1000 + numPix );
  569.         
  570.         if ( !picHdl )
  571.             break;
  572.         
  573.         numPix++;
  574.     } while ( picHdl );
  575.  
  576.     SetResLoad( true );
  577.  
  578.     return numPix;
  579. }
  580.  
  581. Boolean DoCloseWindow( void )
  582. {
  583.     short saveIt;            // This used to be Boolean
  584.     TEHandle    textH;
  585.     
  586.     // return true if we didn't cancel
  587.  
  588.     if ( gDocDirty ){
  589.         saveIt = AskSave();
  590.         
  591.         switch( saveIt ){
  592.             case kASSave:
  593.                 DoSave();
  594.                 break;
  595.             case kASDontSave:
  596.                 break;
  597.             case kASCancel:
  598.                 return false;
  599.                 break;
  600.         }
  601.  
  602.     }
  603.  
  604.     textH = (TEHandle)GetWRefCon( gDocWindow);
  605.  
  606. #ifdef GENERATINGCFM
  607.     DisposeRoutineDescriptor( (*textH)->clickLoop );
  608. #endif
  609.  
  610.     TEDispose( textH );
  611.  
  612.     DisposeControl( gVertScroll );
  613.     gVertScroll = (ControlHandle)NULL;
  614.     
  615.     DisposeWindow( gDocWindow );        
  616.     gDocWindow = (WindowPtr)NULL;
  617.     
  618.     if ( gDocExists ){
  619.         /* If the file exists on disk, close it */
  620.         FSClose( gRefNum );
  621.         if ( gResRefNum != -1 )
  622.             CloseResFile( gResRefNum );
  623.     }
  624.  
  625.     FixMenuMarks();            /* Disable menu items to reflect absent window */
  626.  
  627.     return true;
  628. }
  629.  
  630.     
  631. short AskSave( void )
  632. {
  633.     short    item;
  634.     
  635.     // This used to be a Boolean, but now I return the item
  636.     // number to allow for canceling as well.
  637.     
  638.     item = Alert( rAskSaveID, (ModalFilterUPP)NULL );
  639.  
  640.     return item;
  641. }
  642.  
  643.